//
// Created by zhangrongxiang on 2018/1/26 10:55
// File prod_no_condvar
//
/* prod_no_condvar.c
   A simple POSIX threads producer-consumer example that doesn't use
   a condition variable.
   See also prod_condvar.c.
*/
#include <time.h>
#include <pthread.h>
#include "tlpi_hdr.h"

static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
static int avail = 0;

static void *threadFunc(void *arg) {
    int cnt = atoi((char *) arg);
    int s, j;
    for (j = 0; j < cnt; j++) {
        sleep(1);
        /* Code to produce a unit omitted */
        s = pthread_mutex_lock(&mtx);
        if (s != 0)
            errExitEN(s, "pthread_mutex_lock");
        avail++;        /* Let consumer know another unit is available */
        s = pthread_mutex_unlock(&mtx);
        if (s != 0)
            errExitEN(s, "pthread_mutex_unlock");
    }
    return NULL;
}

int main(int argc, char *argv[]) {
    pthread_t tid;
    int s, j;
    int totRequired;            /* Total number of units that all
                                   threads will produce */
    int numConsumed;            /* Total units so far consumed */
    Boolean done;
    time_t t;
    t = time(NULL);
    /* Create all threads */
    totRequired = 0;
    for (j = 1; j < argc; j++) {
        totRequired += atoi(argv[j]);
        s = pthread_create(&tid, NULL, threadFunc, argv[j]);
        if (s != 0)
            errExitEN(s, "pthread_create");
    }
    /* Use a polling loop to check for available units */
    numConsumed = 0;
    done = FALSE;
    for (;;) {
        s = pthread_mutex_lock(&mtx);
        if (s != 0)
            errExitEN(s, "pthread_mutex_lock");
        while (avail > 0) {             /* Consume all available units */
            /* Do something with produced unit */
            numConsumed++;
            avail--;
            printf("T=%ld: numConsumed=%d\n", (long) (time(NULL) - t),
                   numConsumed);
            done = (Boolean) (numConsumed >= totRequired);
        }
        s = pthread_mutex_unlock(&mtx);
        if (s != 0)
            errExitEN(s, "pthread_mutex_unlock");
        if (done)
            break;
        /* Perhaps do other work here that does not require mutex lock */
    }
    exit(EXIT_SUCCESS);
}